/*
 * QLabelAdapter.cpp  0.4.0 / Nov 29, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
#include "QSplitterAdapter.h"

#include <QMouseEvent>
#include <QPainter>

// QSplitterHandleAdapter :: Public Constructor. -------------------------------

/*!
 * \brief Constructs new QSplitterAdapter object.
 *
 * \param orientation the orientation
 * \param parent the parent
 * \param touchExpandable the \c true if expandable
 */
QSplitterHandleAdapter::QSplitterHandleAdapter(Qt::Orientation orientation,
                                               QSplitter *parent,
                                               bool touchExpandable)
  : QSplitterHandle(orientation, parent), m_mousePosition(Outside),
    m_touchExpandable(touchExpandable)
{
  setMouseTracking(true);
}

//  QSplitterHandleAdapter :: Public Member Function. --------------------------

/*!
 * \brief Sets whether or not the handle is one touch expandable.
 *
 * \param touchExpandable \c true if expandable
 */
void QSplitterHandleAdapter::setTouchExpandable(bool touchExpandable)
{
  m_touchExpandable = touchExpandable;
  if (touchExpandable) {
    calculateArrows();
  }
  update();
}

// QSplitterHandleAdapter :: Overridden Member Functions. ----------------------

/*!
 * \inheritDoc
 */
void QSplitterHandleAdapter::resizeEvent(QResizeEvent *e)
{
  QSplitterHandle::resizeEvent(e);
  if (m_touchExpandable) {
    calculateArrows();
  }
}

/*!
 * \inheritDoc
 */
void QSplitterHandleAdapter::paintEvent(QPaintEvent *e)
{
  QSplitterHandle::paintEvent(e);
  if (m_touchExpandable) {
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    switch (m_mousePosition) {
      case OverFirst:
        painter.setBrush(palette().dark());
        painter.setPen(painter.brush().color());
        painter.drawPolygon(m_firstArrow, 3);
        painter.setBrush(palette().buttonText());
        painter.setPen(painter.brush().color());
        painter.drawPolygon(m_secondArrow, 3);
        break;
      case OverSecond:
        painter.setBrush(palette().buttonText());
        painter.setPen(painter.brush().color());
        painter.drawPolygon(m_firstArrow, 3);
        painter.setBrush(palette().dark());
        painter.setPen(painter.brush().color());
        painter.drawPolygon(m_secondArrow, 3);
        break;
      default:
        painter.setBrush(palette().buttonText());
        painter.setPen(painter.brush().color());
        painter.drawPolygon(m_firstArrow, 3);
        painter.drawPolygon(m_secondArrow, 3);
        break;
    }
  }
}

/*!
 * \inheritDoc
 */
void QSplitterHandleAdapter::enterEvent(QEvent *e)
{
  QSplitterHandle::enterEvent(e);
  if (m_touchExpandable) {
    m_mousePosition = Over;
    update(m_firstArrowRect);
    update(m_secondArrowRect);
  }
}

/*!
 * \inheritDoc
 */
void QSplitterHandleAdapter::leaveEvent(QEvent *e)
{
  QSplitterHandle::leaveEvent(e);
  if (m_touchExpandable) {
    m_mousePosition = Outside;
    update(m_firstArrowRect);
    update(m_secondArrowRect);
  }
}

/*!
 * \inheritDoc
 */
void QSplitterHandleAdapter::mouseMoveEvent(QMouseEvent *e)
{
  QSplitterHandle::mouseMoveEvent(e);
  if (m_touchExpandable) {
    if (m_firstArrowRect.contains(e->x(), e->y(), true)) {
      setCursor(QCursor(Qt::ArrowCursor));
      m_mousePosition = OverFirst;
      update(m_firstArrowRect);
      update(m_secondArrowRect);
    } else if (m_secondArrowRect.contains(e->x(), e->y(), true)) {
      setCursor(QCursor(Qt::ArrowCursor));
      m_mousePosition = OverSecond;
      update(m_firstArrowRect);
      update(m_secondArrowRect);
    } else {
      if (orientation() == Qt::Horizontal) {
        setCursor(QCursor(Qt::SplitHCursor));
      } else {
        setCursor(QCursor(Qt::SplitVCursor));
      }
      m_mousePosition = Over;
      update(m_firstArrowRect);
      update(m_secondArrowRect);
    }
  }
}

/*!
 * \inheritDoc
 */
void QSplitterHandleAdapter::mousePressEvent(QMouseEvent *e)
{
  QSplitterHandle::mousePressEvent(e);
  if (m_touchExpandable) {
    m_pressedPoint = e->pos();
  }
}

/*!
 * \inheritDoc
 */
void QSplitterHandleAdapter::mouseReleaseEvent(QMouseEvent *e)
{
  QSplitterHandle::mouseReleaseEvent(e);
  if (m_touchExpandable) {
    QPoint releasedPoint = e->pos();
    switch (m_mousePosition) {
      case OverFirst:
        if (releasedPoint == m_pressedPoint) {
          static_cast<QSplitterAdapter *>(splitter())->collapseFirst();
        }
        break;
      case OverSecond:
        if (releasedPoint == m_pressedPoint) {
          static_cast<QSplitterAdapter *>(splitter())->collapseSecond();
        }
        break;
      default:
        break;
    }
    m_pressedPoint.setX(-1);
    m_pressedPoint.setY(-1);
  }
}

// QSplitterHandleAdapter :: Private Member Function. --------------------------

void QSplitterHandleAdapter::calculateArrows()
{
  int w2 = width() / 2;
  int h2 = height() / 2;
  if (orientation() == Qt::Horizontal) {
    m_firstArrow[0].setX(w2 - 2);
    m_firstArrow[0].setY(h2 - 30);
    m_firstArrow[1].setX(w2 + 2);
    m_firstArrow[1].setY(h2 - 34);
    m_firstArrow[2].setX(m_firstArrow[1].x());
    m_firstArrow[2].setY(h2 - 26);
    m_firstArrowRect.setCoords(m_firstArrow[0].x() - 2,
                               m_firstArrow[1].y() - 2,
                               m_firstArrow[2].x() + 2,
                               m_firstArrow[2].y() + 2);
    m_secondArrow[0].setX(m_firstArrow[0].x());
    m_secondArrow[0].setY(h2 + 26);
    m_secondArrow[1].setX(m_firstArrow[1].x());
    m_secondArrow[1].setY(h2 + 30);
    m_secondArrow[2].setX(m_firstArrow[0].x());
    m_secondArrow[2].setY(h2 + 34);
    m_secondArrowRect.setCoords(m_firstArrowRect.x(),
                                m_secondArrow[0].y() - 2,
                                m_secondArrow[1].x() + 2,
                                m_secondArrow[2].y() + 2);
  } else {
    m_firstArrow[0].setX(w2 - 30);
    m_firstArrow[0].setY(h2 - 2);
    m_firstArrow[1].setX(w2 - 34);
    m_firstArrow[1].setY(h2 + 2);
    m_firstArrow[2].setX(w2 - 26);
    m_firstArrow[2].setY(m_firstArrow[1].y());
    m_firstArrowRect.setCoords(m_firstArrow[1].x() - 2,
                               m_firstArrow[0].y() - 2,
                               m_firstArrow[2].x() + 2,
                               m_firstArrow[2].y() + 2);
    m_secondArrow[0].setX(w2 + 26);
    m_secondArrow[0].setY(m_firstArrow[0].y());
    m_secondArrow[1].setX(w2 + 30);
    m_secondArrow[1].setY(m_firstArrow[1].y());
    m_secondArrow[2].setX(w2 + 34);
    m_secondArrow[2].setY(m_firstArrow[0].y());
    m_secondArrowRect.setCoords(m_secondArrow[0].x() - 2,
                                m_secondArrow[0].y() - 2,
                                m_secondArrow[2].x() + 2,
                                m_secondArrow[1].y() + 2);
  }
}

// QSplitterAdapter :: Public Constructor. ------------------------------------

/*!
 * \brief Constructs new QSplitterAdapter object.
 */
QSplitterAdapter::QSplitterAdapter()
  : QSplitter(), m_oneTouchExpandable(false)
{
  setChildrenCollapsible(false);
}

// QSplitterAdapter :: Public Member Functions. --------------------------------

/*!
 * \brief Sets handle position.
 *
 * \param position the position
 */
void QSplitterAdapter::setHandlePosition(int position)
{
  if (count() > 0) {
    moveSplitter(position, 1);
  }
}

/*!
 * \brief Sets whether or not the comopnents of the split pane can be quickly
 *        expanded/collapsed.
 *
 * \param oneTouchExpandable \c true if expandable
 */
void QSplitterAdapter::setOneTouchExpandable(bool oneTouchExpandable)
{
  m_oneTouchExpandable = oneTouchExpandable;
  setChildrenCollapsible(oneTouchExpandable);
  if (count() > 0) {
    static_cast<QSplitterHandleAdapter *>(handle(1))->
                                        setTouchExpandable(oneTouchExpandable);
  }
}

/*!
 * \brief Sets resize weight.
 *
 * \param resizeWeight the resize weight
 */
void QSplitterAdapter::setResizeWeight(double resizeWeight)
{
  if (count() == 2) {
    QList<int> sizes;
    int size;
    if (orientation() == Qt::Horizontal) {
      size = sizeHint().width();
    } else {
      size = sizeHint().height();
    }
    sizes.append((int)(size * resizeWeight));
    sizes.append((int)(size * (1 - resizeWeight)));
    setSizes(sizes);
  }
}

/*!
 * \brief Collapses the first widget.
 */
void QSplitterAdapter::collapseFirst()
{
  moveSplitter(0, 1);
}

/*!
 * \brief Collapses the second widget.
 */
void QSplitterAdapter::collapseSecond()
{
  if (orientation() == Qt::Horizontal) {
    moveSplitter(this->width() - handle(1)->width(), 1);
  } else {
    moveSplitter(this->height() - handle(1)->height(), 1);
  }
}

// QSplitterAdapter :: Overridden Member Function. -----------------------------

/*!
 * \inheritDoc
 */
QSplitterHandle *QSplitterAdapter::createHandle()
{
  return new QSplitterHandleAdapter(orientation(), this, m_oneTouchExpandable);
}
